"""Pylons middleware initialization"""
from paste.cascade import Cascade
from paste.registry import RegistryManager
from paste.urlparser import StaticURLParser
from paste.deploy.converters import asbool
from paste.errordocument import StatusBasedForward
from paste.recursive import RecursiveMiddleware

from pylons import config
from pylons.error import error_template
from pylons.middleware import error_mapper, ErrorDocuments, ErrorHandler
from pylons.wsgiapp import PylonsApp
from pylons.controllers.util import abort

from routes.middleware import RoutesMiddleware

from mtp.config.environment import load_environment, configure_mtp
import mtp.lib.helpers as h

from pylons.wsgiapp import PylonsBaseWSGIApp

import logging
log = logging.getLogger(__name__)

def auth_mapper(code, message, environ, global_conf, **kwargs):
    """ used by AuthRedirect """
    if environ.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
        return 
    if code == 401:
        log.debug("sending to %s" % h.url_for('login_form'))
        return h.url_for('login_form')
    elif code == 403:
        log.debug("sending to %s" % h.url_for('permission_denied'))
        return h.url_for('permission_denied')
    

def AuthRedirect(app, global_conf, **kwargs):
    """ middleware to redirect 401 codes to the login page """
    return RecursiveMiddleware(StatusBasedForward(app,
        global_conf=global_conf, mapper=auth_mapper, **kwargs))


class MTPBaseWSGIApp(PylonsBaseWSGIApp):
    def find_controller(self, controller):
        try:
            cont = config['mtp.controllers'][controller]
        except KeyError:
            abort(404)
        else:
            return cont


def make_app(global_conf, full_stack=True, **app_conf):
    """Create a Pylons WSGI application and return it

    ``global_conf``
        The inherited configuration for this application. Normally from
        the [DEFAULT] section of the Paste ini file.

    ``full_stack``
        Whether or not this application provides a full WSGI stack (by
        default, meaning it handles its own exceptions and errors).
        Disable full_stack when this application is "managed" by
        another WSGI middleware.

    ``app_conf``
        The application's local configuration. Normally specified in the
        [app:<name>] section of the Paste ini file (where <name>
        defaults to main).
    """
    # Configure the Pylons environment
    load_environment(global_conf, app_conf)

    configure_mtp()

    # init plugins
    from mtp import model
    for name, plugin in config['mtp.plugins'].iteritems():
        plugin_rec = model.Plugin.get(name)
        if not plugin_rec:
            plugin_rec = model.Plugin(name=name, configured=False)

        if not plugin_rec.configured:
            plugin.setup()
            plugin_rec.configured = True
            plugin_rec.save()

    route_names = config['routes.map']._routenames.keys()
    route_names.sort()
    for name in route_names:
        log.debug("%s = %s" % (name, config['routes.map']._routenames[name].routepath))

    permissions = config['mtp.permissions'].items()
    permissions.sort(cmp=lambda a,b: cmp(a[0], b[0]))
    for perm in permissions:
        log.debug("permission %s %s" % perm)

    # The Pylons WSGI app
    app = PylonsApp(base_wsgi_app=MTPBaseWSGIApp, use_routes=False)

    # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)

    config['routes.middleware'] = app = RoutesMiddleware(app, config['routes.map'])

    app = AuthRedirect(app, global_conf=global_conf, **app_conf)

    if False: #asbool(full_stack):
        # Handle Python exceptions
        app = ErrorHandler(app, global_conf, error_template=error_template,
                           **config['pylons.errorware'])

        # Display error documents for 401, 403, 404 status codes (and
        # 500 when debug is disabled)
        app = ErrorDocuments(app, global_conf, mapper=error_mapper, **app_conf)

    # Establish the Registry for this application
    app = RegistryManager(app)

    # Static files
    #javascripts_app = StaticJavascripts()
    static_app = StaticURLParser(config['pylons.paths']['static_files'])
    app = Cascade([static_app, app])
    return app



